package com.example.demo.config.builder;

import com.example.demo.config.builder.choice.ComplexFormCheckChoiceGuard;
import com.example.demo.config.builder.choice.ComplexFormDealChoiceGuard;
import com.example.demo.config.enum_.ComplexFormEvents;
import com.example.demo.config.enum_.ComplexFormStates;
import com.example.demo.config.event.action.ComplexFormChoiceAction;
import com.example.demo.config.event.action.ComplexFormErrorAction;
import com.example.demo.config.event.action.ComplexForm_DEAL_CHOICE_false_Action;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.statemachine.StateMachine;
import org.springframework.statemachine.annotation.WithStateMachine;
import org.springframework.statemachine.config.EnableStateMachine;
import org.springframework.statemachine.config.StateMachineBuilder;
import org.springframework.stereotype.Component;

import java.util.EnumSet;
import java.util.UUID;

/**
 * 复杂订单状态机构建器 
 * 	流程图 389a2040da9cec8562afa8a1c191b7721d1.jpg
 */
@Component
@EnableStateMachine(name = "complexFormMachine")
public class ComplexFormStateMachineBuilder {
	private static final String MACHINEID="complexFormMachine";
	
	/**
	 * 构建状态机
		* 	创建初始的空白表单（ BLANK_FORM）
		*	填写(WRITE)表单，成为填充完表单（FULL_FORM）
		*	检查(CHEKC)表单
		*	如果是表单名（formName）不为null，表单成为待提交表单（CONFIRM_FROM）
		*	提交（SUBMIT）表单，成为成功提交表单（SUCCESS_FORM）
		*	检查（CHECK）表单
		*	如果表单名为null，表单成为待处理表单（DEAL_FORM）,修改formName
		*	处理(DEAL)表单
		*	如果表单名还是null或者里面有个“坏”字，表单状态变成废单（FAILED_FORM）
		*	如果表单名称没问题，表单状态变成填充完表单状态（FULL_FORM）,重新走流程
	 * @return
	 * @throws Exception
	 */
	public StateMachine<ComplexFormStates, ComplexFormEvents> build(BeanFactory beanFactory) throws Exception {
		StateMachineBuilder.Builder<ComplexFormStates, ComplexFormEvents> builder = StateMachineBuilder.builder();
		System.out.println("构建复杂表单状态机");
		builder.configureConfiguration()
			.withConfiguration()
			.machineId(MACHINEID)
 			.beanFactory(beanFactory);
		
		builder.configureStates()
			.withStates()
			.initial(ComplexFormStates.BLANK_FORM)//初始化的状态
			.choice(ComplexFormStates.CHECK_CHOICE)//判断
			.choice(ComplexFormStates.DEAL_CHOICE)//判断
			.states(EnumSet.allOf(ComplexFormStates.class));
		builder.configureTransitions()
			.withExternal()//空白表单 ==>填写完表单
				.source(ComplexFormStates.BLANK_FORM).target(ComplexFormStates.FULL_FORM)
				.event(ComplexFormEvents.WRITE)
				//在状态变化的时候就能在action里面处理,不同业务用不同的action就行
				//action可以多个插入
				//.action(new ComplexFormChoiceAction())
				.action(new ComplexFormChoiceAction())
				.and()
			.withExternal() //填写完表单 ==>表单校验判断
				.source(ComplexFormStates.FULL_FORM).target(ComplexFormStates.CHECK_CHOICE)
				.event(ComplexFormEvents.CHECK)
				.and()
			.withChoice()
				//first()，last()。这两个代表的就是分支判断时TRUE和FALSE的状态流程去处
				//Guard就承担了这个判断的功能
			
				//判断表单名称是否为null ，如果为不null ===》校验完表单
				.source(ComplexFormStates.CHECK_CHOICE)
				.first(ComplexFormStates.CONFIRM_FORM,new ComplexFormCheckChoiceGuard()
						,new ComplexFormChoiceAction(),new ComplexFormErrorAction())
				//，如果为null ===》待处理表单
				//在状态变化的时候就能在action里面处理,不同业务用不同的action就行
				//action可以多个插入,不止在withChoice()里面可以，之前的withExternal()也是可以
				.last(ComplexFormStates.DEAL_FORM,new ComplexFormChoiceAction()
						,new ComplexFormErrorAction())
				.and()
			.withExternal()// 校验完表单 ===>成功表单
				.source(ComplexFormStates.CONFIRM_FORM).target(ComplexFormStates.SUCCESS_FORM)
				.event(ComplexFormEvents.SUBMIT)
				.and()
			.withExternal()//待处理表单 ===>表单处理校验
				.source(ComplexFormStates.DEAL_FORM).target(ComplexFormStates.DEAL_CHOICE)
				.event(ComplexFormEvents.DEAL)
				.and()
			.withChoice()//表单处理校验
				.source(ComplexFormStates.DEAL_CHOICE)
					//，如果不为废单 ===》填写完表单
				.first(ComplexFormStates.FULL_FORM, new ComplexFormDealChoiceGuard(),new ComplexFormErrorAction())
					//如果为废单 == 》失败表单
				.last(ComplexFormStates.FAILED_FORM,new ComplexForm_DEAL_CHOICE_false_Action(),new ComplexFormErrorAction());
		
		return builder.build();
	}
}
